﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using mshtml;
using System.Xml.Serialization;
using System.Data;
using System.Text.RegularExpressions;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace AutoPageHelper
{
    public enum PageState
    {
        
        Ready = 0,
        Loading = 1,
        Loaded = 2,
        Filled = 3,
        Delayed = 4,
        Timeout = 5,
        Waiting = 6,
        Canceled = 7,
        End = 8, // 提前结束
        Finished = 100
    }
    public enum PageType
    {
        General = 0,
        Start = 1,
        End = 2,
        Other = 100
    }
    public enum TrigMode
    {
        Gernal,
        Nth,
        TopN,
        AfterN,
    }
    [Serializable]
    public class ActionPage
    {
        // key=dataColumn value = elementName
        [NonSerialized]
        private Dictionary<string, string> map = new Dictionary<string, string>();

        [NonSerialized]
        private Dictionary<string, string> data = new Dictionary<string, string>();

        [NonSerialized]
        private IHTMLDocument3 doc = null;

        [NonSerialized]
        private PageState state = PageState.Ready;
        [NonSerialized]
        private int tryTime = 100;
        [NonSerialized]
        private int submitTime = 0;
        [NonSerialized]
        private int tried = 0;
        [XmlIgnore]
        public string DataString
        {
            get { return string.Join("; ", data.Values.ToArray<string>()); }
        }
        [XmlIgnore]
        public PageState State
        {
            get { return state; }
            set { state = value; }
        }

        [XmlIgnore]
        public ActionPage RefPage
        {
            get;
            set;
        }

        [NonSerialized]
        List<List<ActionPage>> prePages;
        public string PrePages
        {
            get;
            set;
        }
        public void SetPrePages(List<ActionPage> pageSet)
        {
            // prePages
            if (string.IsNullOrEmpty(PrePages))
                return;

            string[] pageOr = PrePages.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string or in pageOr)
            {
                string[] pageIds = or.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                if (pageIds == null || pageIds.Length < 1)
                    continue;
                List<ActionPage> orItems = new List<ActionPage>();
                foreach (string Id in pageIds)
                {
                    foreach (ActionPage ppa in pageSet) // find by id
                    {
                        if (ppa.Id.Equals(Id))
                        {
                            orItems.Add(ppa);
                            break;
                        }
                    }
                }
                if (prePages == null)
                    prePages = new List<List<ActionPage>>();
                prePages.Add(orItems);
            }

        }
        public bool IsPrePagesFinished()
        {
            if (prePages == null || prePages.Count < 1)
                return true;

            foreach (List<ActionPage> orItem in prePages)
            {
                if (orItem == null)
                    continue;
                bool bAndFinished = true;
                foreach (ActionPage pa in orItem)
                {
                    if (pa.State != PageState.Finished)
                    {
                        bAndFinished = false;
                        break;
                    }
                }
                if (bAndFinished)
                {
                    return true;
                }
            }
            return false;
        }
        public override string ToString()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ActionPage));
            StringWriter sw = new StringWriter();
            serializer.Serialize(sw, this);
            return sw.ToString();
        }
        public static bool IsRegexUrl(string url)
        {
            if(!string.IsNullOrEmpty(url))
                return url.StartsWith("^");
            return false;
        }
        
        public int TryTime
        {
            get { return tryTime; }
            set
            {
                if (value < 1)
                    value = 1;
                if (value <= submitTime)
                    value = submitTime + 1;
                tryTime = value;
            }
        }
        public int SubmitTime
        {
            get { return submitTime; }
            set
            {
                if (value >= tryTime)
                    value = tryTime - 1;
                submitTime = value;
            }
        }

        public ActionPage()
        {
            //Url = "";
            //UrlNext = "";
            //UrlFailed = "";
            //UrlSuccess = "";
            //Type = "";
            //KeySuccess = "";
            //KeyFailed = "";
            //Action = "";

        }
        public ActionPage(string url)
            : this()
        {
            Url = url;
        }
        public ActionPage(IHTMLDocument doc)
            : this()
        {
            Document = doc;
            if(String.IsNullOrEmpty(Url))
                Url = (doc as IHTMLDocument2).url;
        }

        public ActionPage(string url, IHTMLDocument doc)
            : this(url)
        {
            Document = doc;
        }

        public bool Equals(ActionPage p)
        {
            return p.Id.Equals(Id);
        }

        [XmlAttribute]
        public bool AllowFailed
        {
            get;
            set;
        }
        [XmlAttribute]
        public bool FillOnly
        {
            get;
            set;
        }
        [XmlAttribute]
        public bool MultiFill
        {
            get;
            set;
        }
        [XmlAttribute(AttributeName="id")]
        public string Id
        {
            get;
            set;
        }
        public string Url
        {
            get;
            set;
        }
        [XmlIgnore]
        public Regex RegUrl
        {
            get { return MyUtility.GetRegex(Url); }
        }
        public PageType Type
        {
            set;
            get;
        }
        [XmlIgnore]
        public List<String> MappingKeys
        {
            get {
                if (map != null && map.Keys.Count > 0)
                    return map.Keys.ToList<String>();
                else
                    return new List<String>();
            }
        }
        public string Mapping
        {
            get
            {
                string r = "";
                foreach (string key in map.Keys)
                {
                    r += key + ":" + map[key] + ";";
                }
                return r;
            }
            set
            {
                string[] pairs = value.Split(new char[] { ':', ';' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < pairs.Length - 1; i += 2)
                {
                    pairs[i] = pairs[i].Trim();
                    if (String.IsNullOrEmpty(pairs[i])) // set id using number
                        pairs[i] = (i / 2).ToString();
                    map.Add(pairs[i], pairs[i + 1].Trim());
                }
            }
        }
        public string KeySuccess
        {
            get;
            set;
        }
        public string ActionSuccess
        {
            get;
            set;
        }
        public string UrlSuccess
        {
            get;
            set;
        }
        public string KeyFailed
        {
            get;
            set;
        }
        public string ActionFailed
        {
            get;
            set;
        }
        public string UrlFailed
        {
            get;
            set;
        }
        public string Action
        {
            get;
            set;
        }
        public string UrlNext
        {
            get;
            set;
        }

        [XmlIgnore]
        public IHTMLDocument Document
        {
            set
            {
                doc = value as IHTMLDocument3;
                Init();
            }
            get { return doc as IHTMLDocument; }
        }

        public void Init()
        {
            tried = 0;
            state = PageState.Ready;
            // 检查计数，从前导页完成开始计算
            if(IsPrePagesFinished())
                Counter++;
        }

        

        public void SaveHTML(string htmlFile)
        {
            if (doc == null)
                return;
            StreamWriter sw = new StreamWriter(htmlFile);
            sw.WriteLine("<!-- " + Url + " -->");
            sw.Write(doc.documentElement.outerHTML);
            sw.Close();
        }

        public void InjectFunction(string functionName, string functionCode)
        {
            string js = string.Format("window.{0}={1};", functionName, functionCode);
            ExecuteJS(js);
        }
        public void IgnoreFunction(string functionName)
        {
            string code = "function(){return true;}";
            InjectFunction(functionName, code);
        }

        public void Reload()
        {
            if (doc == null)
                return;
            IHTMLWindow2 win = (doc as IHTMLDocument2).parentWindow; // STA thread
            win.navigate(win.location.href);
            state = PageState.Ready;
        }

        private bool ConditionalAct(string KeyPattern, string action, string url)
        {
            if (!String.IsNullOrEmpty(KeyPattern))
            {
                Regex regKey = new Regex(KeyPattern, RegexOptions.IgnoreCase);
                if ((!String.IsNullOrEmpty(action) || !String.IsNullOrEmpty(url)) 
                    && regKey.IsMatch(doc.documentElement.innerText))
                {
                    if (!String.IsNullOrEmpty(action))
                    {
                        return DoAction(action);
                    }
                    else if (!String.IsNullOrEmpty(url))
                    {
                        NavigateTo(url);
                        return true;
                    }
                }
            }
            return false;
        }

        private void NavigateTo(string url)
        {
            IHTMLDocument2 doc2 = doc as IHTMLDocument2;
            if (doc2 != null && doc2.parentWindow != null)
                doc2.parentWindow.navigate(url);
        }

        public bool DoAction()
        {
            if (tried >= tryTime)
            {
                state = PageState.Timeout;
                return true;
            }
            return DoAction(Action);
        }

        public bool ExecuteJS(string js)
        {
            if (doc == null || string.IsNullOrEmpty(js))
                return false;
            bool bSuccess = false;
            try
            {
                IHTMLWindow2 win = (doc as IHTMLDocument2).parentWindow;// must in a STA thread
                if (win != null)
                {
                    win.execScript(js);
                    bSuccess = true;
                }
            }
            catch(COMException) // JS语法错误
            {
                bSuccess = true;
            }
            catch (Exception) // 其他错误
            {
                bSuccess = false;
            }
            return bSuccess;
        }

        public object ExecuteFunction(string functionName, object[] parameters = null)
        {
            if (doc == null || string.IsNullOrEmpty(functionName))
                return null;
            bool bSuccess = false;
            object result = null;
            try
            {
                IHTMLWindow2 win = (doc as IHTMLDocument2).parentWindow; // must in a STA thread
                if (win != null)
                {
                    result = win.GetType().InvokeMember(functionName, System.Reflection.BindingFlags.InvokeMethod, null, win, parameters);
                    bSuccess = true;
                }
            }
            catch (COMException) // JS语法错误
            {
            }
            catch (Exception) // 其他错误
            {
            }
            if (bSuccess)
                return result;
            return null;
        }

        private IHTMLElement GetElemByOuterHTML(string html)
        {
            int indexg = html.IndexOf('>') + 1;
            if (indexg < 1)
                return null;

            IHTMLElement e0 = (doc as IHTMLDocument2).createElement(html);
            if (e0 == null)
                return null;


            if (indexg < html.Length - 1)
            {
                int indexl = html.IndexOf('<', indexg) - 1;
                if (indexl > indexg)
                {
                    string innerHtml = html.Substring(indexg, indexl - indexg + 1);
                    e0.innerHTML = innerHtml;
                }
            }
            string outerHtml = e0.outerHTML;
            IHTMLElementCollection elems = doc.getElementsByTagName(e0.tagName);
            foreach (IHTMLElement e in elems)
            {
                if (e.outerHTML.Equals(outerHtml, StringComparison.CurrentCultureIgnoreCase))
                    return e;
            }
            return null;
        }

        private IHTMLElement GetElemByRegexHTML(string html)
        {
            html = html.Substring(1, html.Length - 2);
            int indexg = html.IndexOf('>') + 1;
            if (indexg < 1)
                return null;

            IHTMLElement e0 = (doc as IHTMLDocument2).createElement(html);
            if (e0 == null)
                return null;

            if (indexg < html.Length - 1)
            {
                int indexl = html.IndexOf('<', indexg) - 1;
                if (indexl > indexg)
                {
                    string innerHtml = html.Substring(indexg, indexl - indexg + 1);
                    e0.innerHTML = innerHtml;
                }
            }

            Regex reg = MyUtility.GetRegex("^" + e0.outerHTML + "$");
            IHTMLElementCollection elems = doc.getElementsByTagName(e0.tagName);
            foreach (IHTMLElement e in elems)
            {
                if (reg.IsMatch(e.outerHTML))
                    return e;
            }
            return null;
        }

        private bool DoAction(string action)
        {
            
            IHTMLElement elem = null;
            if (String.IsNullOrEmpty(action)) // 空，直接转到NextUrl
            {
                if (!String.IsNullOrEmpty(UrlNext))
                {
                    NavigateTo(UrlNext);
                }
                state = PageState.Finished;
                return true;
            }
            action = action.Trim();
            if (action.StartsWith("javascript:", StringComparison.CurrentCultureIgnoreCase)) // javascript
            {
                string js = action.Substring(11).Trim();
                // fill parameters
                foreach (KeyValuePair<String, String> p in data)
                {
                    js = js.Replace("{" + p.Key + "}", p.Value);
                }
                if (ExecuteJS(js))
                {
                    state = PageState.Finished;
                    return true;
                }
                return false;
            }
            else if (action.StartsWith("ref:", StringComparison.CurrentCultureIgnoreCase)) // reference
            {
                if (RefPage != null)
                {
                    bool bRtn = RefPage.DoAction(RefPage.Action);
                    state = RefPage.State;
                    return bRtn;
                }
                return false;
            }
            else if (action.StartsWith("<") && action.EndsWith(">")) // HTML代码
            {
                elem = GetElemByOuterHTML(action);
                if(elem != null)
                    action = (elem as IHTMLUniqueName).uniqueID; // for next process
            }
            else if (action.StartsWith("^<") && action.EndsWith(">$")) // 正则表达式
            {
                elem = GetElemByRegexHTML(action);
            }
            else if (action.Contains(";") || action.Contains(",")) // ID列表
            {
                string[] btns = action.Split(new char[]{';',','}, StringSplitOptions.RemoveEmptyEntries);
                string btn = ClickAnyButton(btns);
                state = PageState.Finished;
                return (!string.IsNullOrEmpty(btn));
            }
            else // 单个ID或名字
            {
                elem = doc.getElementById(action);
                if (elem == null || elem.tagName == "!") // 转到其他页面
                {
                    IHTMLElementCollection elems = doc.getElementsByName(action);
                    if (elems == null || elems.length < 1)
                        return false;
                    else
                        elem = (IHTMLElement)elems.item(0);
                }
            }

            if (elem != null)
            {
                bool disabled = (elem as IHTMLElement3).disabled;
                if (!disabled)
                {
                    if (elem.tagName.ToUpper() == "FORM")
                        (elem as IHTMLElement3).FireEvent("onsubmit");
                    else
                        elem.click();
                    state = PageState.Finished;
                }
                else
                    state = PageState.Delayed;
                return true;
            }
            else
            {

            }
            return false;
        }

        private bool IsDocChanged()
        {
            IHTMLDocument2 doc2 = doc as IHTMLDocument2;

            //if (!doc2.readyState.ToLower().Equals("complete")) // 状态改变
            //    return true;
            if (!MyUtility.GetRegex(Url).IsMatch(doc2.url)) // url 改变
                return true;
            return false;
        }

        public bool Submit()
        {
            //Debug.Assert(doc != null);
            if (doc == null)
                return false;

            if (state == PageState.Canceled)
                return true;

            if (tried++ >= TryTime)
            {
                state = PageState.Timeout;
                return true;
            }

            // 进来的时候已经是complete，如果有更改说明操作已取消
            if (IsDocChanged())
            {
                state = PageState.Canceled;
                return true;
            }

            if (tried <= SubmitTime) // not error, for sleep 
            {
                state = PageState.Ready;
                return false;
            }

            if (state != PageState.Ready)
                return false;

            IgnoreFunction("confirm");

            if (Fill())
                state = PageState.Filled;
            //else
            //    return false;

            if (this.FillOnly)
            {
                state = PageState.Finished;
                return true;
            }

            if (ConditionalAct(KeyFailed, ActionFailed, UrlFailed))
            {
                state = PageState.End;
                return true;
            }

            if (ConditionalAct(KeySuccess, ActionSuccess, UrlSuccess))
            {
                state = PageState.Finished;
                return true;
            }

            if (DoAction(Action))
            {
                return true;
            }

            return false;
        }

        public string ClickAnyButton(string[] ButtonIds)
        {
            if (doc != null && ButtonIds != null)
            {
                for (int i = ButtonIds.Length - 1; i >= 0; i--)
                {
                    IHTMLElement btn = ClickButton(ButtonIds[i]);
                    if (btn != null)
                        return ButtonIds[i];
                }
            }
            return "";
        }

        public IHTMLElement ClickButton(string id)
        {
            if (doc != null && !String.IsNullOrEmpty(id))
            {
                id = id.Trim();
                IHTMLElement elem = doc.getElementById(id);
                if (elem != null)
                {
                    elem.click();
                    return elem;
                }
            }
            return null;
        }


        public void AddElementMap(string columnName, string elemName)
        {
            map[columnName] = elemName;
            data[columnName] = "";
        }
        public IHTMLElement this[string id]
        {
            get 
            {
                if (doc != null)
                    return doc.getElementById(id);
                else
                    return null;
            }
        }
        public void SetData(string columnName, string dataValue)
        {
            data[columnName] = dataValue;
        }
        public void SetData(Dictionary<string, string> dr)
        {
            if (dr == null)
                return;
            data.Clear();
            foreach (KeyValuePair<String, String> p in map)
            {
                if (dr.Keys.Contains(p.Key))
                    data[p.Key] = dr[p.Key];
            }
        }
        public void SetData(string strData)
        {
            if (string.IsNullOrEmpty(strData))
                return;
            string[] d = strData.Split(new char[] { '\t', ',', '|'});
            int i = 0;
            data.Clear();
            foreach (string k in map.Keys)
            {
                data[k] = d[i++];
                if (i >= d.Length)
                    break;
            }
        }
        public bool Fill()
        {
            bool filled = true;
            foreach (KeyValuePair<String, String> p in map)
            {
                String val = "";
                if(data.Keys.Contains(p.Key))
                    val = data[p.Key];
                if (!SetElemValue2(p.Value, val))
                    filled = false;
            }
            return filled;
        }
        public bool SetElemValue2(string elemName, string val)
        {
            if (doc == null)
                return false;

            if (string.IsNullOrEmpty(elemName))
                return true;
            object obj = (doc as IHTMLDocument2).all.item(elemName.Trim());
            if (obj == null)
                return false;

            IHTMLElement elem = null;
            IHTMLElementCollection elems = null;
            if (obj is IHTMLElementCollection)
            {
                elems = obj as IHTMLElementCollection;
                if (elems != null && elems.length > 0)
                    elem = elems.item(0) as IHTMLElement;
            }
            else
            {
                elem = obj as IHTMLElement;
            }

            if (elem == null)
                return false;


            IHTMLElement3 elem3 = elem as IHTMLElement3;
            string tag = elem.tagName.ToUpper();
            if (tag.Equals("TEXTAREA"))
            {
                HTMLTextAreaElement txtArea = elem as HTMLTextAreaElement;
                txtArea.value = val;
                txtArea.FireEvent("onblur");
                return true;
            }
            else if (tag.Equals("SELECT"))
            {
                HTMLSelectElement slct = elem as HTMLSelectElement;
                string val0 = slct.value;
                slct.value = val;
                if (!val.Equals(val0))
                    slct.FireEvent("onchange");
                return true;
            }
            else if (tag.Equals("INPUT"))
            {
                HTMLInputElement txtInput = elem as HTMLInputElement;
                string type = txtInput.type.ToLower();
                if (type.Equals("text") || type.Equals("password"))
                {
                    string val0 = txtInput.value;
                    txtInput.value = val;
                    if (!val.Equals(val0))
                        txtInput.FireEvent("onchange");
                    txtInput.FireEvent("onblur");
                }
                else if (elems != null && elems.length > 0)
                {
                    if (type.Equals("radio"))
                    {
                        for (int i = 0; i < elems.length; i++)
                        {
                            IHTMLInputElement e = elems.item(i) as IHTMLInputElement;
                            string val0 = e.value;
                            if (val.Equals(val0))
                            {
                                (e as IHTMLElement).setAttribute("checked", true);
                                (e as IHTMLElement3).FireEvent("onclick");
                                return true;
                            }
                        }
                    }
                    else if (type.Equals("checkbox"))
                    {
                        if (elems.length == 1) // 只有一个checkbox
                        {
                            bool chk = !val.StartsWith("--");
                            (elem as IHTMLElement).setAttribute("checked", chk);
                            (elem as IHTMLElement3).FireEvent("onclick");
                            return true;
                        }
                        else // 多个，用值选中，多个值用',', '|', ';'隔开， 如 --val1;--val2;val3;val4
                        {
                            String[] vals = val.Split(new char[] { ',', '|', ';' }, StringSplitOptions.RemoveEmptyEntries);
                            bool[] chk = new bool[vals.Length];
                            for (int j = 0; j < vals.Length; j++)
                            {
                                vals[j] = vals[j].Trim();
                                if (vals[j].StartsWith("--"))
                                {
                                    chk[j] = false;
                                    vals[j] = vals[j].Substring(2);
                                }
                                else
                                    chk[j] = true;
                            }
                            for (int i = 0; i < elems.length; i++)
                            {
                                IHTMLInputElement e = elems.item(i) as IHTMLInputElement;
                                string val0 = e.value;
                                for (int j = 0; j < vals.Length; j++)
                                {
                                    if (val0.Equals(vals[j]))
                                    {
                                        (e as IHTMLElement).setAttribute("checked", chk[j]);
                                        (e as IHTMLElement3).FireEvent("onclick");
                                        break;
                                    }
                                }
                            } // for i
                        }
                    }

                }
                return true;
            }
            return false;
        }

        public bool SetElemValue(string elemName, string val)
        {
            if (doc == null)
                return false;

            if (string.IsNullOrEmpty(elemName))
                return true;
            else if (!MyUtility.IsVariableName(elemName))
                return true;
            else if (IsDocChanged())
                return true;

            elemName = elemName.Trim();

            IHTMLElement elem = null;
            IHTMLElementCollection elems = doc.getElementsByName(elemName);
            if (elems != null && elems.length > 0)
                elem = (IHTMLElement)elems.item(0);
            else
                elem = doc.getElementById(elemName);

            if (elem == null)
                return false;

            string type = (string)elem.getAttribute("type");
            if (type == "text" || type == "password")
            {
                IHTMLElement3 elem3 = elem as IHTMLElement3;
                elem.setAttribute("value", val);
                elem3.FireEvent("onblur");
                return true;
            }
            else if (elem.tagName.ToUpper() == "TEXTAREA")
            {
                IHTMLElement3 elem3 = elem as IHTMLElement3;
                elem.innerText = val;
                elem3.FireEvent("onblur");
                return true;
            }
            else if (elem.tagName.ToUpper() == "SELECT")
            {
                IHTMLElementCollection opts = elem.children as IHTMLElementCollection;//elem.GetElementsByTagName("OPTION");

                if (opts != null)
                {
                    for (int i = 0; i < opts.length; i++)
                    {
                        IHTMLElement opt = (IHTMLElement)opts.item(i);
                        if (opt.tagName.ToUpper() == "OPTION")
                        {
                            if (((string)opt.getAttribute("value")).Equals(val.Trim()) 
                                || opt.innerText.Equals(val.Trim()))
                            {
                                opt.setAttribute("selected", "true");
                            }
                            else
                            {
                                opt.setAttribute("selected", "");
                            }
                        }
                    }
                    IHTMLElement3 elem3 = elem as IHTMLElement3;
                    elem3.FireEvent("onchange");
                    return true;
                }
            }
            else if (type == "radio" && elems != null && elems.length > 0)
            {
                for (int i = 0; i < elems.length; i++)
                {
                    IHTMLElement e = (IHTMLElement)elems.item(i);
                    if (((string)e.getAttribute("value")).Equals(val.Trim()))
                    {
                        e.click();
                        return true;
                    }
                }
            }
            else if (type == "checkbox" && elems != null && elems.length > 0)
            {
                if (elems.length == 1) // 只有一个checkbox
                {
                    
                    elem.click();
                    return true;
                }
                else
                {
                    String[] vals = val.Split(new char[] { ',', '|', ';' }, StringSplitOptions.RemoveEmptyEntries);

                    for (int i = 0; i < elems.length; i++)
                    {
                        IHTMLElement e = (IHTMLElement)elems.item(i);
                        string sv = (string)e.getAttribute("value");
                        int j = 0;
                        for (j = 0; j < vals.Length; j++)
                        {
                            if (sv == vals[j].Trim())
                            {
                                e.click();
                                break;
                            }
                        }
                    } // for
                    return true;
                }
            } // if checkbox
            return false;
        }

        public TrigMode TrigType
        {
            get;
            set;
        }

        public int TrigTime
        {
            get;
            set;
        }


        [XmlIgnore]
        public int Counter
        {
            get;
            set;
        }
        [XmlIgnore]
        public bool CanTriggered
        {
            get 
            {
                bool bTrigger = true;
                switch (TrigType)
                {
                    case TrigMode.Nth:
                        bTrigger = (Counter == TrigTime);
                        break;
                    case TrigMode.Gernal:
                        bTrigger = true;
                        break;
                    case TrigMode.TopN:
                        bTrigger = (Counter <= TrigTime);
                        break;
                    case TrigMode.AfterN:
                        bTrigger = (Counter > TrigTime);
                        break;
                }
                return (bTrigger && IsPrePagesFinished());
            }
        }
    }


}
